﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.Xml.Serialization;
using Tomahawk.Runtime.Canvas.Sprite;
using Tomahawk.Runtime.Rendering.Interfaces;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Tomahawk.Runtime.Canvas;
using Tomahawk.Runtime.Resources;

namespace Tomahawk.Runtime.Logic.UI.Components
{
    /// <summary>
    /// Reusable simple Image renderer
    /// </summary>
    public struct ImageComponent
    {
        /// <summary>
        /// Resource pool
        /// </summary>
        [XmlAttribute("pool")]
        public ResourceManager.ResourcePool ResourcePool;

        /// <summary>
        /// Indicates the texture this image component will use
        /// </summary>
        [XmlAttribute("texture")]
        public string textureAsset;

        /// <summary>
        /// Indicates the effect channel this image component will use
        /// </summary>
        [XmlAttribute("effectChannel")]
        public string effectChannel;

        private string localizedTextureAsset;

        private UISprite sprite;

        private CanvasManager.CanvasLayers canvasLayer;

        private bool localized;

        /// <summary>
        /// Height of the original texture.
        /// </summary>
        public float OriginalHeight
        {
            get { return sprite.OriginalHeigth; }
        }

        /// <summary>
        /// Width of the original texture.
        /// </summary>
        public float OriginalWidth
        {
            get { return sprite.OriginalWidth; }
        }

        /// <summary>
        /// Source Rectangle.
        /// </summary>
        public Rectangle SourceRectangle
        {
            get 
            {
                if (sprite == null) return Rectangle.Empty;
                return sprite.SourceRectangle; 
            }
            set 
            {
                if (sprite != null) sprite.SourceRectangle = value; 
            }
        }

        /// <summary>
        /// Set sprite effect
        /// </summary>
        public void SetEffect(SpriteEffects effect)
        {
            if (this.sprite != null) this.sprite.Effect = effect;
        }

        /// <summary>
        /// Initialization
        /// </summary>
        public void Initialize(CanvasManager.CanvasLayers canvasLayer)
        {
            //save canvas layer for future use
            this.canvasLayer = canvasLayer;

            if (this.effectChannel == null)
            {
                this.effectChannel = "Default";
            }

            if ((this.textureAsset != null) && (this.textureAsset != ""))
            {
                //localized?
                this.localized = this.textureAsset.StartsWith("##");
                if (this.localized)
                {
                    Engine.Instance.LocalizationManager.GetLocalizedString(this.textureAsset, out this.localizedTextureAsset);
                    Engine.Instance.LocalizationManager.LanguageChanged += new Tomahawk.Runtime.Localization.LanguageChangedDelegate(LocalizationManager_LanguageChanged);
                }
                else
                {
                    this.localizedTextureAsset = this.textureAsset;
                }

                //create the sprite
                this.createSprite(canvasLayer);
            }
        }

        private void createSprite(CanvasManager.CanvasLayers canvasLayer)
        {
            //Create an UISprite primitive and register it
            this.sprite = new UISprite(this.localizedTextureAsset, this.effectChannel, this.ResourcePool);
            Engine.Instance.CanvasManager.GetUISpriteRenderer(canvasLayer).AddPrimitive(sprite);
        }

        /// <summary>
        /// Change the localized texture on language change
        /// </summary>
        void LocalizationManager_LanguageChanged(Tomahawk.Runtime.Localization.LocalizationManager.Language newLanguage)
        {
            Engine.Instance.LocalizationManager.GetLocalizedString(this.textureAsset, out this.localizedTextureAsset);

            if (this.sprite != null)
            {
                UISprite oldSprite = this.sprite;

                this.destroySprite();
                this.createSprite(canvasLayer);

                //copy values
                sprite.Depth = oldSprite.Depth;
                sprite.DestinationRectangle = oldSprite.DestinationRectangle;
                sprite.Color = oldSprite.Color;
                sprite.SourceRectangle = oldSprite.SourceRectangle;

                //release oldsprite
                oldSprite = null;
            }

        }

        /// <summary>
        /// Changes the visibility of the component
        /// </summary>
        public void SetVisibility(bool value)
        {
            if (sprite != null)
            {
                sprite.Visible = value;
            }
        }

        /// <summary>
        /// Changes the position of the component
        /// </summary>
        public void SetPosition(ref Rectangle rect)
        {
            if (sprite != null)
            {
                sprite.DestinationRectangle.X = rect.X;
                sprite.DestinationRectangle.Y = rect.Y;
                sprite.DestinationRectangle.Width = rect.Width;
                sprite.DestinationRectangle.Height = rect.Height;
            }
        }

        /// <summary>
        /// Changes the rotation of the component
        /// </summary>
        public void SetRotation(float rotation, ref Vector2 origin)
        {
            if (sprite != null)
            {
                sprite.Rotation = rotation;
                sprite.Origin = origin;
            }
        }

        /// <summary>
        /// Changes the depth of the component
        /// </summary
        public void SetDepth(float depth)
        {
            if (sprite != null)
            {
                sprite.Depth = depth;
            }
        }

        /// <summary>
        /// Returns if the component is valid (i.e. correctly initialized)
        /// </summary>
        public bool IsValid()
        {
            return (sprite != null);
        }

        /// <summary>
        /// Destruction
        /// </summary>
        public void Destroy()
        {   
            //unsubscribe to localization
            if (this.localized)
            {
                Engine.Instance.LocalizationManager.LanguageChanged -= LocalizationManager_LanguageChanged;
            }

            this.destroySprite();
        }

        private void destroySprite()
        {
            if (sprite != null)
            {
                Engine.Instance.CanvasManager.GetUISpriteRenderer(this.canvasLayer).RemovePrimitive(sprite);
            }
            sprite = null;
        }

        /// <summary>
        /// Is the component ready?
        /// </summary>
        public bool IsReady()
        {
            bool retVal = true;
            if (sprite != null) retVal = sprite.IsReady;
            return retVal;
        }

        /// <summary>
        /// Gets or sets the image alpha
        /// </summary>
        public byte Alpha
        {
            get
            {
                return (sprite != null) ? sprite.Color.A : (byte)0;
            }
            set
            {
                if (sprite != null) sprite.Color.A = value;
            }
        }

        /// <summary>
        /// Sets the color of the sprite
        /// </summary>
        public void SetColor(ref XStyleManager.FontColor color)
        {
            if (sprite != null)
            {
                this.sprite.Color.A = color.A;
                this.sprite.Color.B = color.B;
                this.sprite.Color.G = color.G;
                this.sprite.Color.R = color.R;
            }
        }

    }

}
